<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="K1uia" id="K1uia"><span data-lake-id="u910e1df4" id="u910e1df4">典型回答</span></h1>
  <p data-lake-id="u2e987404" id="u2e987404"><br></p>
  <p data-lake-id="u168a1d3d" id="u168a1d3d"><span data-lake-id="uc05bb367" id="uc05bb367">Netty作为一个使用广泛的网络通信框架，他的代码也是值得学习的，在Netty中也用到了很多种设计模式。比如单例模式、工厂模式、责任链模式、观察者模式、策略模式、装饰者模式等。</span></p>
  <p data-lake-id="u5590660b" id="u5590660b"><span data-lake-id="uc5cb5955" id="uc5cb5955">​</span><br></p>
  <h1 data-lake-id="ySCGd" id="ySCGd"><span data-lake-id="u08a07537" id="u08a07537">扩展知识</span></h1>
  <h2 data-lake-id="Db72v" id="Db72v"><span data-lake-id="u917e09ba" id="u917e09ba">单例模式</span></h2>
  <p data-lake-id="u32c6013a" id="u32c6013a"><br></p>
  <p data-lake-id="u3ba127d5" id="u3ba127d5"><span data-lake-id="ueef4f9bf" id="ueef4f9bf">NioEventLoop 通过核心方法 select() 不断轮询注册的 I/O 事件，Netty 提供了选择策略 SelectStrategy 对象，这个对象就是个单例：</span></p>
  <p data-lake-id="ua3ba6054" id="ua3ba6054"><span data-lake-id="u3da3f6e2" id="u3da3f6e2">​</span><br></p>
  <pre lang="java"><code>
final class DefaultSelectStrategy implements SelectStrategy {

    static final SelectStrategy INSTANCE = new DefaultSelectStrategy();

    private DefaultSelectStrategy() { }

    @Override

    public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception {

        return hasTasks ? selectSupplier.get() : SelectStrategy.SELECT;

    }

}
</code></pre>
  <p data-lake-id="u083cfa34" id="u083cfa34"><span data-lake-id="uf4c51119" id="uf4c51119">​</span><br></p>
  <p data-lake-id="u7dd58127" id="u7dd58127"><span data-lake-id="ubf6fc564" id="ubf6fc564">还有其中定义的异常：</span></p>
  <p data-lake-id="u7668c5e1" id="u7668c5e1"><span data-lake-id="ue1235e6d" id="ue1235e6d">​</span><br></p>
  <pre lang="java"><code>
public final class ReadTimeoutException extends TimeoutException {

    private static final long serialVersionUID = 169287984113283421L;

    public static final ReadTimeoutException INSTANCE = new ReadTimeoutException();

    private ReadTimeoutException() { }
}
</code></pre>
  <p data-lake-id="uf2a9f3c2" id="uf2a9f3c2"><br></p>
  <h2 data-lake-id="unKj6" id="unKj6"><span data-lake-id="ub76097e8" id="ub76097e8">工厂模式</span></h2>
  <p data-lake-id="uf6c5d920" id="uf6c5d920"><br></p>
  <p data-lake-id="u6e80bbbd" id="u6e80bbbd"><span data-lake-id="udc7da4e1" id="udc7da4e1">工厂模式是一个比较常见的设计模式，在很多框架中都会用到，Netty也不例外，只要我们的Netty中搜索Factory，得到的类几乎都是和工厂模式有关的。</span></p>
  <p data-lake-id="uc6ddea85" id="uc6ddea85"><span data-lake-id="ub52fcf84" id="ub52fcf84">​</span><br></p>
  <p data-lake-id="u22f10594" id="u22f10594"><span data-lake-id="u46f8ab2b" id="u46f8ab2b">如我们前面提到的SelectStrategy也是用工厂创建的：</span></p>
  <p data-lake-id="uc235f10b" id="uc235f10b"><span data-lake-id="u75e9d889" id="u75e9d889">​</span><br></p>
  <pre lang="java"><code>
public final class DefaultSelectStrategyFactory implements SelectStrategyFactory {
    public static final SelectStrategyFactory INSTANCE = new DefaultSelectStrategyFactory();

    private DefaultSelectStrategyFactory() { }

    @Override
    public SelectStrategy newSelectStrategy() {
        return DefaultSelectStrategy.INSTANCE;
    }
}
</code></pre>
  <p data-lake-id="u5ff81ce3" id="u5ff81ce3"><br></p>
  <h2 data-lake-id="dGN2T" id="dGN2T"><span data-lake-id="ub4fca257" id="ub4fca257">装饰者模式</span></h2>
  <p data-lake-id="u38d156b3" id="u38d156b3"><span data-lake-id="u3e01eae2" id="u3e01eae2">Netty中的WrappedByteBuf就是你对ByteBuf的装饰。来实现对他的增强：</span></p>
  <p data-lake-id="uf58b4e43" id="uf58b4e43"><br></p>
  <pre lang="java"><code>
class WrappedByteBuf extends ByteBuf {

    protected final ByteBuf buf;

    protected WrappedByteBuf(ByteBuf buf) {
        if (buf == null) {
            throw new NullPointerException("buf");
        }
        this.buf = buf;
    }

    @Override
    public final boolean hasMemoryAddress() {
        return buf.hasMemoryAddress();
    }

    //....
    
}
</code></pre>
  <p data-lake-id="u85f88c17" id="u85f88c17"><br></p>
  <h2 data-lake-id="qVvmA" id="qVvmA"><span data-lake-id="u453a6691" id="u453a6691">责任链模式</span></h2>
  <p data-lake-id="ud671faea" id="ud671faea"><br></p>
  <p data-lake-id="u060c09da" id="u060c09da"><span data-lake-id="u628db3ed" id="u628db3ed">责任链在Netty中用的比较多，Netty中有大量的</span><a href="https://github.com/netty/netty/blob/d34212439068091bcec29a8fad4df82f0a82c638/transport/src/main/java/io/netty/channel/ChannelPipeline.java" target="_blank" data-lake-id="ub66b8b67" id="ub66b8b67"><span data-lake-id="ue863e929" id="ue863e929">ChannelPipeline</span></a><span data-lake-id="u159b1038" id="u159b1038">，而这些Pipeline就是通过责任链来驱动的。</span></p>
  <p data-lake-id="u7d04f189" id="u7d04f189"><br></p>
  <h2 data-lake-id="Lo4pL" id="Lo4pL"><span data-lake-id="ua7c47bdf" id="ua7c47bdf">策略模式</span></h2>
  <p data-lake-id="uf20d5845" id="uf20d5845"><br></p>
  <p data-lake-id="u84550233" id="u84550233"><br></p>
  <p data-lake-id="u23162458" id="u23162458"><span data-lake-id="ue93fdd94" id="ue93fdd94">Netty 在多处地方使用了策略模式，例如 </span><a href="https://github.com/netty/netty/blob/d34212439068091bcec29a8fad4df82f0a82c638/common/src/main/java/io/netty/util/concurrent/DefaultEventExecutorChooserFactory.java" target="_blank" data-lake-id="ufe17b667" id="ufe17b667"><span data-lake-id="u5397f39c" id="u5397f39c">EventExecutorChooser</span></a><span data-lake-id="u040a1789" id="u040a1789"> 提供了不同的策略选择 NioEventLoop，newChooser() 方法会根据线程池的大小情况来动态选择取模运算的方式：</span></p>
  <p data-lake-id="u9cb29625" id="u9cb29625"><span data-lake-id="u97c9b78c" id="u97c9b78c">​</span><br></p>
  <pre lang="java"><code>
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {

    public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();

    private DefaultEventExecutorChooserFactory() { }

    @Override
    public EventExecutorChooser newChooser(EventExecutor[] executors) {
        if (isPowerOfTwo(executors.length)) {
            return new PowerOfTwoEventExecutorChooser(executors);
        } else {
            return new GenericEventExecutorChooser(executors);
        }
    }
}
</code></pre>
  <p data-lake-id="uc7438d08" id="uc7438d08"><br></p>
  <p data-lake-id="u43d8b7fc" id="u43d8b7fc"><span data-lake-id="u79318b3d" id="u79318b3d">而这里的PowerOfTwoEventExecutorChooser和GenericEventExecutorChooser是是EventExecutorChooser的两种具体策略实现：</span></p>
  <p data-lake-id="u80a60b60" id="u80a60b60"><span data-lake-id="u237dd816" id="u237dd816">​</span><br></p>
  <pre lang="java"><code>
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        private final AtomicInteger idx = new AtomicInteger();
        private final EventExecutor[] executors;

        PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[idx.getAndIncrement() &amp; executors.length - 1];
        }
    }

    private static final class GenericEventExecutorChooser implements EventExecutorChooser {
        // Use a 'long' counter to avoid non-round-robin behaviour at the 32-bit overflow boundary.
        // The 64-bit long solves this by placing the overflow so far into the future, that no system
        // will encounter this in practice.
        private final AtomicLong idx = new AtomicLong();
        private final EventExecutor[] executors;

        GenericEventExecutorChooser(EventExecutor[] executors) {
            this.executors = executors;
        }

        @Override
        public EventExecutor next() {
            return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
        }
    }
</code></pre>
 </body>
</html>